package recite.word.client.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import recite.word.client.dto.word.*;
import recite.word.client.service.IBookService;
import recite.word.client.service.IUserService;
import recite.word.client.service.IUserWordService;
import recite.word.client.service.IWordService;
import recite.word.client.vo.word.*;
import recite.word.mybatis.auto.dao.WordMapper;
import recite.word.mybatis.auto.model.User;
import recite.word.mybatis.auto.model.UserWord;
import recite.word.mybatis.auto.model.Word;
import recite.word.service.base.common.enums.DeleteEnum;
import recite.word.service.base.common.enums.WordListTypeEnum;
import recite.word.service.base.common.request.BaseRequest;
import recite.word.service.base.common.threadLocal.UserContent;
import recite.word.service.base.util.common.Asserts;
import recite.word.service.base.util.date.DateFormat;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: recite-word-back
 * @description:
 * @author: Mr.lin
 * @create: 2023-01-02 19:44
 **/
@Service
public class WordServiceImpl extends ServiceImpl<WordMapper, Word> implements IWordService {
    @Autowired
    private IUserService userService;
    @Autowired
    private IBookService bookService;
    @Autowired
    private IUserWordService userWordService;

    String auditPrefix = "https://ali.bczcdn.com/r/";

    /**
     * 获取单词列表
     * @param dto
     * @return
     */
    @Override
    public IPage<WordListVO> wordList(BaseRequest<WordListDTO> dto) {
        WordListDTO data = dto.getData();
        Asserts.isTrue(ObjectUtil.isNotNull(data.getType()),"类型不能为空");
        Page<UserWord> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        LambdaQueryWrapper<UserWord> wrapper = new LambdaQueryWrapper<UserWord>()
                .eq(UserWord::getUserId, UserContent.get())
                .eq(UserWord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode());
        // 根据条件构建wrapper
        if (data.getType().equals(WordListTypeEnum.BOOK.getType())){  // 书籍
            Long bookId = data.getBookId();
            Asserts.isNotNull(bookId,"单词书id不能为空");
            wrapper.eq(UserWord::getBookId, bookId);
        } else if (data.getType().equals(WordListTypeEnum.COLLECT.getType())){  // 收藏
            wrapper.eq(UserWord::getIsCollection,true);
        } else if (data.getType().equals(WordListTypeEnum.WRONG.getType())) { // 错题
            wrapper.eq(UserWord::getIsWrong,true);
        }
        // 分页查询
        Page<UserWord> userWordPage = userWordService.page(page, wrapper);
        List<WordListVO> collect = userWordPage.getRecords().stream().map(item ->
                WordListVO.builder()
                        .wordId(item.getId())
                        .accent(item.getAccent())
                        .isCollection(item.getIsCollection() == 1)
                        .meanCn(item.getMeanCn())
                        .word(item.getWord())
                        .wordAudio(auditPrefix + item.getWordAudio())
                        .build()).collect(Collectors.toList());
        IPage ans = userWordPage;
        ans.setRecords(collect);
        return ans;
    }

    /**
     * 变更收藏状态
     * @param dto
     */
    @Override
    public void changeCollect(BaseRequest<ChangeCollectDTO> dto) {
        ChangeCollectDTO data = dto.getData();
        boolean b = userWordService.update(new LambdaUpdateWrapper<UserWord>()
                .eq(UserWord::getId, data.getWordId())
                .eq(UserWord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .set(UserWord::getIsCollection, data.getCollectStatus()));
        Asserts.isTrue(b, "变更收藏失败");
    }

    /**
     * 获取单词详情
     * @param dto
     * @return
     */
    @Override
    public WordInfoVO getWordInfo(BaseRequest<WordInfoDTO> dto) {
        WordInfoDTO data = dto.getData();
        UserWord userWord = userWordService.getById(data.getWordId());
        StringBuilder place = new StringBuilder();
        List<Word> list = this.list(new LambdaQueryWrapper<Word>()
                .eq(Word::getWord, userWord.getWord())
                .eq(Word::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .orderByDesc(Word::getBookId));

        if (CollUtil.isNotEmpty(list)) {
            for (Word word : list) {
                String simpleName = bookService.getById(word.getBookId()).getSimpleName();
                place.append(" / ").append(simpleName);
            }
            place.delete(0,3);
        }
        String[] meanCnSplit = userWord.getMeanCn().split("\\.");
        return WordInfoVO.builder()
                .accent(userWord.getAccent())
                .deformationImg(userWord.getDeformationImg())
                .place(place.toString())
                .meanEn(userWord.getMeanEn())
                .sentence(userWord.getSentence())
                .sentenceAudio(auditPrefix + userWord.getSentenceAudio())
                .sentencePhrase(userWord.getSentencePhrase())
                .sentenceTrans(userWord.getSentenceTrans())
                .word(userWord.getWord())
                .prefix(meanCnSplit[0])
                .wordAudio(auditPrefix + userWord.getWordAudio())
                .isCollection(userWord.getIsCollection() == 1)
                .meanCn(meanCnSplit[1])
                .wordEtyma(userWord.getWordEtyma())
                .build();
    }

    /**
     * 获取背单词的详情
     * @param dto
     * @return
     */
    @Override
    public ReciteInfoVO getReciteInfo(BaseRequest<ReciteInfoDTO> dto) {
        // 根据auto_id向下取5个单词,
        ReciteInfoDTO data = dto.getData();
        UserWord userWord = userWordService.getById(data.getWordId());
        List<ReciteOptionWord> optionWords = new ArrayList<>();
        for (int i = 1; i < 5; i++) {
            int autoId = userWord.getAutoId() + i;
            UserWord option = userWordService.getOne(new LambdaQueryWrapper<UserWord>().eq(UserWord::getAutoId, autoId));
            ReciteOptionWord optionWord = toReciteOptionWord(option);
            optionWords.add(optionWord);
        }
        ReciteOptionWord collectOptionWord = toReciteOptionWord(userWord);
        collectOptionWord.setIsCorrect(true);
        if (optionWords.size() < 4) {
            optionWords.add(collectOptionWord);
        } else {
            Random random = new Random();
            int collectIndex = random.nextInt(4);// 0 - 3之间的整数
            optionWords.set(collectIndex,collectOptionWord);
        }
        String[] meanCnSplit = userWord.getMeanCn().split("\\.");
        return ReciteInfoVO.builder()
                .accent(userWord.getAccent())
                .deformationImg(userWord.getDeformationImg())
                .isCollection(userWord.getIsCollection() == 1)
                .meanCn(meanCnSplit[1])
                .prefix(meanCnSplit[0])
                .wordAudio(auditPrefix + userWord.getWordAudio())
                .meanEn(userWord.getMeanEn())
                .sentence(userWord.getSentence())
                .sentenceAudio(auditPrefix + userWord.getSentenceAudio())
                .sentencePhrase(userWord.getSentencePhrase())
                .sentenceTrans(userWord.getSentenceTrans())
                .word(userWord.getWord())
                .wordEtyma(userWord.getWordEtyma())
                .reciteOptionWords(optionWords)
                .build();
    }

    /**
     * 获取今天的单词id
     * @return
     */
    @Override
    public DayWordIdVO getDayWordIds() {
        String toDay = DateFormat.format(new Date());
        Long userId = UserContent.get();
        User user = userService.getById(userId);
        // 今天已经学习的单词数
        int todayStudyNum = userWordService.count(new LambdaQueryWrapper<UserWord>()
                .eq(UserWord::getUserId, userId)
                .eq(UserWord::getBookId, user.getPlanBookId())
                .eq(UserWord::getIsRecite, true)
                .eq(UserWord::getReciteDate, toDay)
                .eq(UserWord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
        int wordNum = user.getEverydayWordNum() - todayStudyNum;
        if (wordNum <= 0) return null;
        List<UserWord> list = userWordService.list(new LambdaQueryWrapper<UserWord>()
                .select(UserWord::getId)
                .eq(UserWord::getUserId, userId)
                .eq(UserWord::getBookId, user.getPlanBookId())
                .eq(UserWord::getIsRecite, false)
                .eq(UserWord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                .last("limit " + wordNum));
        List<Long> wordIds = list.stream().map(UserWord::getId).collect(Collectors.toList());
        DayWordIdVO dayWordIdVO = new DayWordIdVO();
        dayWordIdVO.setWordIds(wordIds);
        return dayWordIdVO;
    }

    /**
     * 设置单词已学习
     * @return
     */
    @Override
    public void setWordStudy(BaseRequest<WordStudyDTO> dto) {
        WordStudyDTO data = dto.getData();
        Long wordId = data.getWordId();
        UserWord userWord = userWordService.getById(wordId);
        Asserts.isTrue(ObjectUtil.isNotNull(userWord),"单词不存在");
        userWord.setIsRecite(Byte.valueOf("1"));
        userWord.setIsWrong(Byte.valueOf("0"));
        String today = DateFormat.format(new Date());
        userWord.setReciteDate(today);
        boolean b = userWordService.updateById(userWord);
        Asserts.isTrue(b,"设置失败");
    }

    /**
     * 设置单词错误
     * @param dto
     */
    @Override
    public void setWordWrong(BaseRequest<WordWrongDTO> dto) {
        WordWrongDTO data = dto.getData();
        Long wordId = data.getWordId();
        UserWord userWord = userWordService.getById(wordId);
        Asserts.isTrue(ObjectUtil.isNotNull(userWord),"单词不存在");
        userWord.setIsRecite(Byte.valueOf("1"));
        userWord.setIsWrong(Byte.valueOf("1"));
        String today = DateFormat.format(new Date());
        userWord.setReciteDate(today);
        boolean b = userWordService.updateById(userWord);
        Asserts.isTrue(b,"设置失败");
    }

    private ReciteOptionWord toReciteOptionWord(UserWord option) {
        if (option == null) return null;
        ReciteOptionWord optionWord = new ReciteOptionWord();
        String[] optionWordCn = option.getMeanCn().split("\\.");
        optionWord.setWord(option.getWord());
        optionWord.setWordId(option.getId());
        optionWord.setIsCorrect(false);
        optionWord.setPrefix(optionWordCn[0]);
        optionWord.setMeanCn(optionWordCn[1]);
        return optionWord;
    }

}
